#include "userclient.h"
#include "string.h"
#include "etc.h"
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <pthread.h>

#define DOWN_HANDLE_BASE 3000 //下载录像句柄 = 用户句柄 + DOWN_HANDLE_BASE

void* threadDownFile(void* p)
{
    printf("threadDownFile start\n");
    UserClient* user = (UserClient*)p;

    if(!user)
    {
        printf("user==NULL\n");
        return NULL;
    }

    if(!user->m_pFile)
    {
        printf("NULL == user->m_pFile\n");
        return NULL;
    }

    if(-1 == user->m_iDownloadSock)
    {
        printf("-1 == user->m_iDownloadSock\n");
        return NULL;
    }
    printf("m_iDownloadSock=%d\n",user->m_iDownloadSock);

    MSG_DOWNFILEDATA msgDownData;//用来缓存下载录像数据的结构

    while(!user->m_bStop)
    {
        if((-1==user->m_iDownloadSock)||(-1==user->m_iSock))
        {
            printf("m_iSock:%d,m_iDownloadSock:%d\n",user->m_iSock,user->m_iDownloadSock);
            break;
        }
        int iReadLen = fread(msgDownData.cBuf,sizeof(char),MAX_FRAME_SIZE,user->m_pFile);
        printf("threadDownFile iReadLen: %d\n",iReadLen);

       //文件已读完
       if(0 == iReadLen)
       {
           msgDownData.msgHead.lHead = FIFO_HEAD;
           msgDownData.msgHead.lRealDataSize = iReadLen + sizeof(MSG_DOWNFILE_HEAD) + sizeof(MSG_REALPLAY_HEAD);
           msgDownData.msgDownHead.iSize = 0;
           msgDownData.msgDownHead.iEnd = 1;
           user->SendMsg(user->m_iDownloadSock,(char*)(&msgDownData),sizeof(MSG_DOWNFILEDATA));

           printf("Download File finish\n");
           break;
       }
       else
       {
           msgDownData.msgHead.lHead = FIFO_HEAD;
           msgDownData.msgHead.lRealDataSize = iReadLen + sizeof(MSG_DOWNFILE_HEAD) + sizeof(MSG_REALPLAY_HEAD);
           msgDownData.msgDownHead.iSize = iReadLen;
           if(iReadLen == MAX_FRAME_SIZE)
           {
               msgDownData.msgDownHead.iEnd = 0;
               user->SendMsg(user->m_iDownloadSock,(char*)(&msgDownData),sizeof(MSG_DOWNFILEDATA));
               continue;
           }
           //文件已读完
           else if(iReadLen < MAX_FRAME_SIZE)
           {
               msgDownData.msgDownHead.iEnd = 1;
               user->SendMsg(user->m_iDownloadSock,(char*)(&msgDownData),sizeof(MSG_DOWNFILEDATA));

               printf("Download File finish\n");
               break;
           }
       }
       usleep(50000);
    }
    user->m_bStop=true;
    user->closeSocket(user->m_iDownloadSock);
    printf("Download thread exit!\n");
}


UserClient::UserClient()
{
    m_iSock = -1;
    m_iDownloadSock = -1;
    m_hDownHandle = -1;
    m_addr = 0;
    m_bStop = false;
    m_hHandle = -1;
    m_fd = NULL;
    m_iFileIndex = 0;
    m_iMaxFileNum = 0;
    memset(m_strPath,0,sizeof(m_strPath));
}

UserClient::~UserClient()
{

}

int UserClient::SendMsg(int Socket ,char *SendBuf, int MsgLen)
{
    int TotalLen = 0;
    while (TotalLen < MsgLen)
    {
        int sendlen = send (Socket, SendBuf+TotalLen, MsgLen - TotalLen, 0);
        if (sendlen < 0)
        {
            perror ("send");
            close(Socket);
            return -1;
        }
        TotalLen += sendlen;
    }
    usleep(50000);
    return TotalLen;
}

int UserClient::Excute()
{
    //init data
    m_bStop = true;
    usleep(40000);
    m_bStop = false;
    m_hDownHandle = -1;

    char RecvBuf[2048*6];
    int MsgLen;
    fd_set fdSocket;

    while(1)
    {
        //printf("user recv thread start,userHandle=%d,sock=%d\n",user->GetUserHandle(),user->m_CommandSock);
        if(-1 == m_hHandle || -1 == m_iSock)
        {
            printf("m_hHandle = %d,m_iSock = %d\n",m_hHandle,m_iSock);
            break;
        }
        FD_ZERO(&fdSocket);
        FD_SET(m_iSock,&fdSocket);
       // printf("recv select start\n");
        timeval tv;
        tv.tv_sec = 2;
        tv.tv_usec = 0;
        int iRet = select(m_iSock+1,&fdSocket,NULL,NULL,&tv);

        // printf("recv select stop,ret = %d\n",iRet);
        if(0 == iRet)
        {
            continue;
        }
        else if(0 > iRet)
        {
            perror("select");
            break;
        }
        else
        {
            //printf("user recv start\n");
            MsgLen = recv(m_iSock,RecvBuf,sizeof(RecvBuf),0);
            if(MsgLen>0)
                ProcessMsg(RecvBuf, MsgLen);
            else
                break;
        }

    }
    CloseFindRecord_EXT();
    m_bStop=true;
    closeSocket(m_iSock);
    printf("user recv thread exit\n");
    return 1;
}

int UserClient::ProcessMsg(char *Msg, int BufLen)
{
    printf("Client ProcessMsg start,the sock = %d\n",m_iSock);
    MSG_HEAD msgHead;
    memcpy(&msgHead,Msg,sizeof(MSG_HEAD));
    printf("msgHead.iCmdType=%d\n",msgHead.iCmdType);

    switch(msgHead.iCmdType)
    {
      case MSG_CLIENT_LOGIN:
      {
            printf("recv login message\n");
            MSG_LOGIN msgLogin;
            memcpy(&msgLogin,Msg,sizeof(MSG_LOGIN));
            int handle = Login(msgLogin.cUserName,msgLogin.cUserPwd);

            MSG_RESULT msgResult;
            msgResult.msgHead.iCmdType = MSG_CLIENT_LOGIN_RE;
            msgResult.msgHead.iMsgSize = sizeof(MSG_RESULT);
            msgResult.iRet = handle;
            SendMsg(m_iSock ,(char*)&msgResult, sizeof(MSG_RESULT));

            break;
      }
      case MSG_CLIENT_FIND_RECORD:
      {
            printf("recv find record message\n");
            MSG_FIND_RECORD msgFindRecord;
            memset(&msgFindRecord,0,sizeof(MSG_FIND_RECORD));
            memcpy(&msgFindRecord,Msg,sizeof(MSG_FIND_RECORD));
            FindRecord_EXT(msgFindRecord);
            break;
      }
      case MSG_CLIENT_FINDNEXT_RECORD:
      {
            MSG_FINDNEXT_RECORD msgFindNext;
            memcpy(&msgFindNext,Msg,sizeof(MSG_FINDNEXT_RECORD));
            FindNextRecord_EXT(msgFindNext);
            break;
      }
      case MSG_CLIENT_DOWNFILE_BYNAME:
      {
            printf("recv down file message\n");
            MSG_DOWNFILE_BYNAME msgDown;
            memset(&msgDown,0,sizeof(MSG_DOWNFILE_BYNAME));
            memcpy(&msgDown,Msg,sizeof(MSG_DOWNFILE_BYNAME));
            DownVideoFile(msgDown);
      }
      break;
    }
}

int UserClient::Login(char* cName,char* cPwd)
{
    char name[USERNAME_LEN],pwd[USERPWD_LEN];
    //从配置文件中读取用户名，密码
    //从配置文件中读取用户名，密码
    GHANDLE EtcHandle;
    EtcHandle = LoadEtcFile (USER_CFG_FILE);
    if (EtcHandle)
    {

            GetValueFromEtc (EtcHandle, "user0", "username", name, sizeof (name));
            GetValueFromEtc (EtcHandle, "user0", "password", pwd, sizeof (pwd));
            UnloadEtcFile (EtcHandle);
    }
    else
    {
            printf("ERROR: #%s% Open File [%s] Error",__FUNCTION__,USER_CFG_FILE);
    }

    printf("User:%s,Password:%s\n",name,pwd);
    if(0 == strcmp(cName,name) && 0 == strcmp(cPwd,pwd))
    {
        printf("login successful\n");
        return m_hHandle;
    }
    else
    {
        printf("login failed\n");
        return -1;
    }
}
int UserClient::FindRecord(MSG_FIND_RECORD findRecord)
{
    MSG_RESULT msgResult;
    msgResult.msgHead.iCmdType = MSG_CLIENT_FIND_RECORD_RE;
    msgResult.msgHead.iMsgSize = sizeof(MSG_RESULT);
    if(-1 == m_iSock)
    {
        printf("FindRecord m_iSock == -1\n");
        return -1;//客户端连接失败
    }
    if(-1 == m_hHandle)
    {
        printf("FindRecord m_hHandle == -1\n");
        msgResult.iRet = MSG_ERROR_NO_LOGIN;
    }
    //int iRet = m_recordManager.QueryRecordFiles(&m_vecFindResult);
    int iRet = REC_QueryRecord (0, &m_vecFindResult);
    printf("QueryRecordFiles return %d\n",iRet);
    msgResult.iRet = m_hHandle;

    printf("m_vecFindResult.size() = %d\n",m_vecFindResult.size());
    if(m_vecFindResult.size() > 0)
    {
        m_it = m_vecFindResult.begin();
    }

    SendMsg(m_iSock,(char*)&msgResult,sizeof(msgResult));
    return 1;
}

//lFindState : 1000-获取文件信息成功；1001-未查找到文件；1002-正在查找请等待；1003-没有更多文件，查找结束；1004-查找文件异常
int UserClient::FindNextRecord(MSG_FINDNEXT_RECORD msgFindNext)
{
    MSG_FIND_RECORD_RE msgRecord;
    memset(&msgRecord,0,sizeof(MSG_FIND_RECORD));

    if(0 == m_vecFindResult.size())
    {
        msgRecord.iRet = MSG_FILE_NOFIND;
        SendMsg(m_iSock,(char*)&msgRecord,sizeof(MSG_FIND_RECORD_RE));
        return 1;
    }
    if(m_it == m_vecFindResult.end())
    {
        msgRecord.iRet = MSG_FILE_NOMOREFILE;
        SendMsg(m_iSock,(char*)&msgRecord,sizeof(MSG_FIND_RECORD_RE));
        return 1;
    }
    else
    {
        msgRecord.lFileSize = m_it->nFileSize;
        msgRecord.iRet = MSG_FILE_SUCCESS;
        memcpy(msgRecord.sFileName,m_it->szFileName,FIND_RECORD_LEN);
        SendMsg(m_iSock,(char*)&msgRecord,sizeof(MSG_FIND_RECORD_RE));
        m_it++;
        return 1;
    }
}
int UserClient::DownVideoFile(MSG_DOWNFILE_BYNAME& msgDown)
{
    MSG_RESULT msgResult;
    msgResult.msgHead.iCmdType = MSG_CLIENT_DOWNFILE_RE;
    msgResult.msgHead.iMsgSize = sizeof(MSG_RESULT);
    if(-1 == m_hHandle)
    {
        printf("111111111111111 -1 == m_hHandle\n");
        msgResult.iRet = MSG_ERROR_NO_LOGIN;
        SendMsg(m_iSock,(char*)&msgResult,sizeof(MSG_RESULT));
        return -1;
    }
    if(-1 != m_hDownHandle)
    {
        printf("22222222222222222 -1 != m_hDownHandle\n");
        msgResult.iRet = MSG_ERROR_ALREADY_DOWNFILE;
        SendMsg(m_iSock,(char*)&msgResult,sizeof(MSG_RESULT));
        return -1;
    }

    char cPath[RECORD_PATH_LEN];
    memset(cPath,0,RECORD_PATH_LEN);
    memcpy(cPath,m_strPath,sizeof(cPath));

    ////int iRet=0; /*= m_recordManager.RecordFilePath(cPath);*/
    //REC_GetRecordFilePath (cPath, 36);;
    //printf("RecordFilePath = %s\n",cPath);
    strcat(cPath,"/");
    strcat(cPath,msgDown.cFileName);//
    printf("filename = %s\n",cPath);

    /*if(msgDown.lUserID != m_hHandle)
    {
        printf("Download ID ERROR,userID=%d,handle=%d\n",msgDown.lUserID,m_hHandle);
         msgResult.iRet = MSG_ERROR_USERHANDLE;
         SendMsg(m_iSock,(char*)&msgResult,sizeof(MSG_RESULT));
         return -1;
    }*/
    m_pFile= fopen(cPath,"rb");//
    if(NULL == m_pFile)
    {
         printf("DownVideoFile fopen failed\n");
         msgResult.iRet = MSG_ERROR_NOFILE;
         SendMsg(m_iSock,(char*)&msgResult,sizeof(MSG_RESULT));
         return -1;
    }

    m_hDownHandle = m_hHandle + DOWN_HANDLE_BASE;
    printf("m_hDownHandle=%d,m_hHandle=%d\n",m_hDownHandle,m_hHandle);
    msgResult.iRet = m_hDownHandle;
    SendMsg(m_iSock,(char*)&msgResult,sizeof(MSG_RESULT));
    m_bStop = false;

    //开启下载文件线程
    pthread_t threadDownload;
    pthread_attr_t attr = {0};
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
    int ret = pthread_create(&threadDownload,&attr,threadDownFile,this);
    if (ret != 0)
    {
        perror ("pthread_create");
        return -1;
    }

    return 0;
}

void UserClient::closeSocket(int& sock)
{
    if(-1!=sock)
    {
        close(sock);
        sock = -1;
    }
}

int UserClient::FindRecord_EXT(MSG_FIND_RECORD findRecord)
{
    //默认
    int CMAIp = 2650908864;//指定CMA，根据IP
    int type = 1;//操作类型，0为录像，1为图片


    MSG_RESULT msgResult;
    msgResult.msgHead.iCmdType = MSG_CLIENT_FIND_RECORD_RE;
    msgResult.msgHead.iMsgSize = sizeof(MSG_RESULT);
    msgResult.iRet = MSG_ERROR_STREAM_CONNECT;;

    if(-1 == m_iSock)
    {
        printf("FindRecord m_iSock == -1\n");
        return -1;//客户端连接失败
    }
    if(-1 == m_hHandle)
    {
        printf("FindRecord m_hHandle == -1\n");
        msgResult.iRet = MSG_ERROR_NO_LOGIN;
    }
    //int iRet = m_recordManager.QueryRecordFiles(&m_vecFindResult);

    //文件夹
    //REC_GetRecordFilePath (m_strPath, 36);;
    //从配置文件中读取录像存放目录
    GHANDLE EtcHandle;
    EtcHandle = LoadEtcFile (RECORD_SERVER_CFG);
    if (EtcHandle)
    {

            GetValueFromEtc (EtcHandle, "PATH", "path", m_strPath, sizeof (m_strPath));
            UnloadEtcFile (EtcHandle);
    }
    else
    {
            printf("ERROR: #%s% Open File [%s] Error",__FUNCTION__,RECORD_SERVER_CFG);
            return -1;
    }

    char temp[256]={0};

    if(0 == type)
        sprintf(temp, "/%u/RecordFiles", CMAIp);
    else if(1 == type)
        sprintf(temp, "/%u/PicFiles", CMAIp);

    strcat(m_strPath,temp);
    printf("m_strPath = %s\n",m_strPath);

    int iRet = access(m_strPath,F_OK);//文件夹不存在，则创建文件夹
    if(iRet == 0)
    {//存在文件记录
        if(0 == type)
            sprintf(temp, "cd %s;ls *.mp4 > %s/tempfilelist", m_strPath,m_strPath);
        else if(1 == type)
            sprintf(temp, "cd %s;ls *.jpg > %s/tempfilelist", m_strPath,m_strPath);
        //sprintf(temp, "cd %s;ls *.mp4 > %s/tempfilelist", m_strPath,m_strPath);
        iRet = system(temp);

        if(0 == iRet)
        {
            sprintf(temp, "%s/tempfilelist", m_strPath);
            m_fd = fopen(temp,"r");

            if(m_fd)
            {
                fgets(temp, 256, m_fd);
                while(!feof(m_fd))
                {
                    fgets(temp, 256, m_fd);
                    m_iMaxFileNum++;
                }

                fseek(m_fd,0,SEEK_SET);
                msgResult.iRet = m_hHandle;
                printf("m_iMaxFileNum = %d\n",m_iMaxFileNum);
            }
        }


        /*sleep(1);
        sprintf(temp, "%s/tempfilelist", m_strPath);

        m_fd = fopen(temp,"r");

        sprintf(temp, "wc -l %s/tempfilelist", m_strPath);
        m_iMaxFileNum = system(temp);

        msgResult.iRet = m_hHandle;

        printf("m_iMaxFileNum = %d\n",m_iMaxFileNum);*/
    }
    else
    {
        printf("ERROR: NO FILE EXSIT");
    }


    //int iRet = REC_QueryRecord (0, &m_vecFindResult);
    //printf("QueryRecordFiles return %d\n",iRet);

    SendMsg(m_iSock,(char*)&msgResult,sizeof(msgResult));
    return 1;
}

//lFindState : 1000-获取文件信息成功；1001-未查找到文件；1002-正在查找请等待；1003-没有更多文件，查找结束；1004-查找文件异常
int UserClient::FindNextRecord_EXT(MSG_FINDNEXT_RECORD msgFindNext)
{
    m_iFileIndex++;
    char path[RECORD_PATH_LEN],name[256];
    memcpy(path,m_strPath,sizeof(m_strPath));
    strcat(path,"/");
    fgets(name,256,m_fd);
    name[strlen(name)-1] = '\0';
    strcat(path,name);

    MSG_FIND_RECORD_RE msgRecord;
    memset(&msgRecord,0,sizeof(MSG_FIND_RECORD));

    if(0 == m_iMaxFileNum)
    {
        msgRecord.iRet = MSG_FILE_NOFIND;
        SendMsg(m_iSock,(char*)&msgRecord,sizeof(MSG_FIND_RECORD_RE));
        return 1;
    }
    if(m_iFileIndex > m_iMaxFileNum)
    {
        msgRecord.iRet = MSG_FILE_NOMOREFILE;
        SendMsg(m_iSock,(char*)&msgRecord,sizeof(MSG_FIND_RECORD_RE));
        return 1;
    }
    else
    {
        struct stat statbuff;
        if(stat(path, &statbuff) < 0)
        {
            printf("????????????????????????path:%s\n",path);
            perror("stat");
            msgRecord.lFileSize = 0;
        }
        else
        {
            msgRecord.lFileSize = statbuff.st_size;
        }

        //msgRecord.lFileSize = m_it->nFileSize;
        msgRecord.iRet = MSG_FILE_SUCCESS;
        memcpy(msgRecord.sFileName,name,FIND_RECORD_LEN);
        SendMsg(m_iSock,(char*)&msgRecord,sizeof(MSG_FIND_RECORD_RE));
        //m_it++;
        return 1;
    }
}

int UserClient::CloseFindRecord_EXT()
{
    if(NULL == m_fd)
        return 0;
    m_iFileIndex = 0;
    fclose(m_fd);
    m_fd = NULL;
    return 0;
}
